package DAO;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import Pojo.Aluno;
import Pojo.Disciplina;
import Pojo.Historico;
import Pojo.HistoricoTurma;
import Pojo.Nota;

/** Classe AlunoDao
 * Essa classe implementa a interface AlunoDao para comunicar com arquivo. 
 * @author Thiago de Sousa Silveira
 *
 */
public class AlunoDaoImplArquivo implements AlunoDao {
	
	/** Lista de Alunos.*/
	private List<Aluno> listaAlunos;
	
	/** Atributo constante com o endereço do arquivo onde será armazenada os dados.*/
	private static final String nomeArquivo = "Arquivos/Alunos.txt";
	
	/** Atributo onde é guardado o próximo id para inserção na lista.*/
	private int proximoId;
	
	/**
	 * Construtor da classe com um identificador indicando que não é necessário buscar dados do arquivo
	 * @param identificador
	 */
	public AlunoDaoImplArquivo(int identificador){
		this.listaAlunos = new ArrayList<Aluno>();
		this.proximoId=0;
	}
	
	/**
	 * Construtor da classe que busca dados no arquivo
	 */
	public AlunoDaoImplArquivo(){
		this.listaAlunos = new ArrayList<Aluno>();
		this.proximoId=0;
		this.buscarArmazenamento();
	}
	
	/**
	 * Getter do próximo id do Aluno
	 * @return próximo id disponível
	 */
	public int getProximoId(){
		return(this.proximoId);
	}
	
	/**
	 * Lista dos Alunos. 
	 * @return Lista dos Alunos.
	 */
	public List<Aluno> getListaAlunos(){
		return(this.listaAlunos);
	}
	
	/**
	 * Busca Armazenamento no arquivo, trata os dados e monta a lista dos alunos.
	 */
	private void buscarArmazenamento(){
		try{
			this.listaAlunos = new ArrayList<Aluno>();
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    Aluno aluno;
		    String dados[];
		    List<Historico> listaHistorico = new ArrayList<Historico>();
		    List<HistoricoTurma> listaHistoricoTurma = new ArrayList<HistoricoTurma>();
		    List<Nota> listaNota = new ArrayList<Nota>();
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	listaHistorico = this.buscarHistoricos(Integer.parseInt(dados[0]));
		    	listaHistoricoTurma = this.buscarHistoricoDeTurmas(Integer.parseInt(dados[0]));
		    	listaNota = this.buscarNotas(Integer.parseInt(dados[0]));
		    	aluno = new Aluno(Integer.parseInt(dados[0]),dados[1],dados[2],listaHistorico,listaHistoricoTurma,listaNota);
		    	this.listaAlunos.add(aluno);
		    	linha = lerArq.readLine();						//Lê as linhas.
		    	this.proximoId=Integer.parseInt(dados[0]);
		    }
		    this.proximoId++;
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Busca no armazenamento usando o id de um aluno. É usado para quando não se quer carregar os dados para a lista.
	 * @param idAluno
	 * @return Aluno
	 */
	public Aluno buscarArmazenamentoProcurarPorId(int idAluno){
		try{
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    String dados[];
		    Aluno aluno;
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	if (Integer.parseInt(dados[0])==idAluno){
		    		aluno = new Aluno(Integer.parseInt(dados[0]),dados[1],dados[2]);
		    		return(aluno);
		    	}
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
		return(null);
	}
	
	/**
	 * Método usado para salvar a lista do arquivo. O arquivo é sobrescrito nesse método.
	 */
	private void salvarArmazenamento(){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(nomeArquivo));
			Iterator<Aluno> i = listaAlunos.iterator();
			
			Aluno aluno;
			while(i.hasNext()){
				aluno = (Aluno) i.next();
				out.write(aluno.toString());
			}
			
			out.close();
			
			
		} catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Método de adicionar o Aluno na lista. 
	 * É verificado se ele o código dele já existe, pois se existir não pode ser adicionado.
	 * Após inserir, o método "salvarArmazenamento()" é chamado
	 * @param aluno
	 * @return true se foi possível inserir ou falso se ele foi encontrado na lista.
	 */
	public boolean adicionarAluno(Aluno aluno){
		Iterator<Aluno> i = listaAlunos.iterator();
		Aluno alunoComparacao;
		while(i.hasNext()){
			alunoComparacao = (Aluno) i.next();
			if (alunoComparacao.getIdAluno() == aluno.getIdAluno()){
				return(false);
			}
		}
		this.listaAlunos.add(aluno);
		this.proximoId++;
		this.salvarArmazenamento();
		return(true);
	}
	
	/**
	 * Método para remover aluno da lista. 
	 * Após remover o método "salvarArmazenamento" é chamado
	 * @param aluno
	 * @return true se o aluno foi encontrado na lista para ser removido ou false se ele não foi encontrado.
	 */
	public boolean removerAluno(Aluno aluno){
		Iterator<Aluno> i = listaAlunos.iterator();
		Aluno alunoComparacao;
		boolean resultado;
		while(i.hasNext()){
			alunoComparacao = (Aluno) i.next();
			if (alunoComparacao.getIdAluno() == aluno.getIdAluno()){
				resultado = this.listaAlunos.remove(alunoComparacao);
				this.salvarArmazenamento();
				return(resultado);
			}
		}
		return(false);
	}
	
	/**
	 * Pesquisa de Alunos passando o cpf
	 * @param cpf
	 * @return Aluno cujo cpf é o que foi passado, ou um null indicando que nenhum aluno foi encontrado
	 */
	public Aluno procurarPorCpf(String cpf){
		Iterator<Aluno> i = listaAlunos.iterator();
		Aluno aluno;
		while(i.hasNext()){
			aluno = (Aluno) i.next();
			if (aluno.getCpf().equals(cpf)){
				return(aluno);
			}
		}
		return(null);
	}
	
	/**
	 * Pesquisa de Alunos passando o nome
	 * @param nome
	 * @return Lista de Alunos cujos nomes são iguais ao que foi passado por parâmetro. 
	 * Essa lista pode não ter nenhum Aluno, o que indica que a pesquisa não encontrou ninguém.
	 */
	public List<Aluno> procurarPorNome(String nome){
		List<Aluno> listaAlunosNome = new ArrayList<Aluno>();
		
		Iterator<Aluno> i = listaAlunos.iterator();
		Aluno aluno;
		while(i.hasNext()){
			aluno = (Aluno) i.next();
			if (aluno.getNome().equals(nome)){
				listaAlunosNome.add(aluno);
			}
		}
		
		return(listaAlunosNome);
	}
	
	/**
	 * Pesquisa de Alunos passando o id do Aluno
	 * @param id
	 * @return Aluno cujo id é igual ao id passado, ou null se nada for encontrado
	 */
	public Aluno procurarPorId(int id){
		
		Iterator<Aluno> i = listaAlunos.iterator();
		Aluno aluno;
		while(i.hasNext()){
			aluno = (Aluno) i.next();
			if (aluno.getIdAluno() == id ){
				return(aluno);
			}
		}
		return(null);
	}
	
	/**
	 * Método para buscar os históricos que está relacionado com alunos
	 * @param idAluno
	 * @return Lista de Históricos
	 */
	private List<Historico> buscarHistoricos(int idAluno){
		HistoricoDaoImplArquivo historicoDao = new HistoricoDaoImplArquivo();
		return(historicoDao.buscarArmazenamentoProcurarPorAluno(idAluno));
	}
	
	/**
	 * Método para buscar os HistóricosTurma que está relcionado com alunos
	 * @param idAluno
	 * @return Lista de Históricos
	 */
	private List<HistoricoTurma> buscarHistoricoDeTurmas(int idAluno){
		HistoricoTurmaDaoImplArquivo historicoTurmaDao = new HistoricoTurmaDaoImplArquivo();
		return(historicoTurmaDao.buscarArmazenamentoProcurarPorAluno(idAluno));
	}
	
	/**
	 * Método para buscar Notas que estão relacionadas com o aluno.
	 * @param idAluno
	 * @return Lista de Notas.
	 */
	private List<Nota> buscarNotas(int idAluno){
		NotaDaoImplArquivo notaDao = new NotaDaoImplArquivo();
		return(notaDao.buscarArmazenamentoProcurarPorAluno(idAluno));
	}
			
}
